﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AvaProvi
{
    [Serializable]
    public class clsAnalisisCapitalizacionRentas_CRN:clsEstado,IControlEstados
    {
        #region Propiedades 
        public clsTerreno_CRN Terreno { get; set; }
        public double SuperficieDeConstrucciones { get { return Convert.ToDouble(this.Terreno.AnalisisFisico.SuperficieDeConstrucciones); } }
        public double SupConstRentaM2 { get { return this.Terreno.Inmueble.EnfoqueDeMercado.ValorHomologadoDeRentasAplicable; } }
        public double SumaDeSuperficies
        {
            get
            {
                return this.SuperficieAccesoria + this.SuperficieDeConstrucciones;
            }
        }
        public double SumaRentasMensuales
        {
            get
            {
                return this.SupAccesoriaRentaMensual + this.SupConstRentaMensual;
            }
        }
        public double RentaBrutaAnual
        {
            get
            {
                return this.SumaRentasMensuales * 12;
            }
        }
        public double RentaBrutaAnualMenosVacios
        {
            get
            {
                return this.RentaBrutaAnual - this.MontoVacios;
            }
        }
        public double MontoTotalSuperficies
        {
            get
            {
                return Convert.ToDouble(this.Terreno.AnalisisFisico.ValorParcialDeConstrucciones) + this.Terreno.AnalisisFisico.ValorParcialDeAreasComunes + this.Terreno.AnalisisFisico.ValorParcialDeSupAccesoria;
            }
        }
        public double SuperficieAccesoria { get { return this.Terreno.AnalisisFisico.SuperficieAccesoriaTotal; } }
        public double SupAccesoriaRentaM2 { get; set; }
        public double SupAccesoriaRentaMensual
        {
            get
            {
                return this.Terreno.AnalisisFisico.SuperficieAccesoriaTotal * this.SupAccesoriaRentaM2;
            }
        }
        public double SupConstRentaMensual
        {
            get
            {
                return Convert.ToDouble(this.Terreno.AnalisisFisico.SuperficieDeConstrucciones) * this.SupConstRentaM2;
            }
        }
        public double Vacios { get; set; }
        public double MontoVacios
        {
            get
            {
                return this.Vacios * RentaBrutaAnual;
            }
        }
        public double Administracion { get; set; }
        public double MontoAdministracion
        {
            get
            {
                return this.Administracion * this.RentaBrutaAnual;
            }
        }
        public int AniosConservacion { get; set; }
        public double MontoConservacion
        {
            get
            {
                return (this.MontoTotalSuperficies / Convert.ToDouble(this.AniosConservacion)) * 0.02;
            }
        }
        public double PorcentajeConservacion { get; set; }
        public double Predial { get; set; }
        public double MontoPredial
        {
            get
            {
                return this.Predial * this.RentaBrutaAnualMenosVacios;
            }
        }
        public double Seguro { get; set; }
        public double MontoSeguro
        {
            get
            {
                return this.Seguro * this.MontoTotalSuperficies;
            }
        }
        public double DepreciacionFiscal { get; set; }
        public double MontoDepreciacionFiscal
        {
            get
            {
                return this.DepreciacionFiscal * this.MontoTotalSuperficies;
            }
        }
        public double SumaDeduccionesFiscales
        {
            get
            {
                return this.MontoAdministracion + this.MontoConservacion + this.MontoPredial + this.MontoSeguro + this.MontoDepreciacionFiscal;
            }
        }
        public string DeduccionOpcional { get; set; }
        public double PorcentajeDeduccionOpcional
        {
            get
            {
                if (this.DeduccionOpcional == "Uso Habitacional")
                    return 0.50;
                if (this.DeduccionOpcional == "Uso Comercial")
                    return 0.35;
                return 0;
            }
        }
        public double MontoDeduccionOpcional
        {
            get
            {
                return PorcentajeDeduccionOpcional * this.RentaBrutaAnualMenosVacios;
            }
        }
        public double DeduccionMayor
        {
            get
            {
                if (this.SumaDeduccionesFiscales > this.MontoDeduccionOpcional)
                    return this.SumaDeduccionesFiscales;
                else
                    return this.MontoDeduccionOpcional;
            }
        }
        public double UtilidadAntesDeImpuestos
        {
            get
            {
                return this.RentaBrutaAnualMenosVacios - this.DeduccionMayor;
            }
        }
        public string TipoDePersona { get; set; }
        public double PorcentajeISR
        {
            get
            {
                if (this.TipoDePersona == "Moral")
                    return 0.30;
                if (this.TipoDePersona == "Física")
                    return 0.03;
                return 0;
            }
        }
        public double MontoISR
        {
            get
            {
                return this.UtilidadAntesDeImpuestos * PorcentajeISR;
            }
        }
        public double PorcentajePTU
        {
            get
            {
                if (this.UtilidadAntesDeImpuestos > 300000.00 || this.UtilidadAntesDeImpuestos == 300000.00)
                    return 10;
                else
                    return 0;
            }
        }
        public double MontoPTU
        {
            get
            {
                return this.PorcentajePTU * this.RentaBrutaAnualMenosVacios;
            }
        }
        public double SumaDeDeducciones
        {
            get
            {
                return this.MontoAdministracion + this.MontoSeguro + this.MontoPredial + this.MontoConservacion + this.MontoISR + this.MontoPTU;
            }
        }
        public double PorcentajeDeDeducciones
        {
            get
            {
                return this.SumaDeDeducciones / this.RentaBrutaAnual;
            }
        }
        public double IngresoNetoAnual
        {
            get
            {
                return this.RentaBrutaAnualMenosVacios - this.SumaDeDeducciones;
            }
        }
        public double TIIE { get; set; }
        public double InflacionEstimada { get; set; }
        public double AnioActual { get; set; }
        public double AnioAnterior { get; set; }
        public decimal VUR
        {
            get

            {
                int contador;

                contador=this.Terreno.Construccion.TiposDeConstruccion.Count;
                decimal sumaVur = (from construccion in this.Terreno.Construccion.TiposDeConstruccion 
                                   select construccion.VUR).Sum();
                
                return contador;
            }
        }
        public double PorcentajeVUR
        {
            get
            {
                double porcentaje;

                porcentaje = Convert.ToDouble(this.VUR);
                if (porcentaje == 0.0) { porcentaje = 0.0; }
                else { porcentaje = Convert.ToDouble(this.VUR); }
                return 1.0 / porcentaje;
            }
        }
        public double TasaDeCapitalizacion { get { return this.TIIE - this.InflacionEstimada + this.PorcentajeVUR; } }
        public double TasaCapitalizacionMensual { get { return this.TasaDeCapitalizacion / 12; } }
        public string Fuente { get; set; }
        public DateTime Fecha { get; set; }
        public DateTime INPC { get; set; }
        public string LinkFuente { get; set; }
        public string Observaciones { get; set; }
        public double IngresoMensual { get { return this.IngresoNetoAnual / 12; } }
        public decimal EdadEnMeses { get { return this.VUR * 12; } }
        public double ValorDeCapitalizacion
        {
            get
            { 
                double resultado = 1 + this.TasaCapitalizacionMensual;
                resultado = Math.Pow(resultado, -Convert.ToDouble(this.EdadEnMeses));
                resultado = 1-resultado;
                resultado = resultado * this.IngresoMensual;
                return resultado /this.TasaCapitalizacionMensual;
            }
        }
        #endregion

        public clsAnalisisCapitalizacionRentas_CRN(clsTerreno_CRN objTerreno):base()
        {
            this.Administracion = 0;
            this.AnioActual = 114.45;
            this.AnioAnterior = 110.5;
            this.AniosConservacion = 0;
            this.DeduccionOpcional = string.Empty;
            this.DepreciacionFiscal = 0;
            this.Fecha = DateTime.Today;
            this.Fuente = string.Empty;
            this.InflacionEstimada = 0;
            this.INPC = DateTime.Today;
            this.LinkFuente = string.Empty;
            this.Observaciones = string.Empty;
            this.PorcentajeConservacion = 0;
            this.Predial = 0;
            this.Seguro = 0;
            this.SupAccesoriaRentaM2 = 0;
            this.Terreno = objTerreno;
            this.TIIE = 0;
            this.Vacios = 0;
            this.TipoDePersona = string.Empty;
        }


        #region Métodos

        public bool Guardar()
        {
            if (this.DatosValidos())
            {
                if (this.EsNuevo)
                    return CreaAnalisis();
                else
                {
                    if (this.EsModificado)
                        return ActualizaAnalisis();
                    else
                        return EliminaAnalisis();
                }
            }
            return false;
        }

        private bool CreaAnalisis()
        {
            clsAnalisisCapitalizacionRentas_CD objAnalisis_CD = new clsAnalisisCapitalizacionRentas_CD();
            if (objAnalisis_CD.CreaNuevoAnalisis(this))
            {
                this.EsModificado = true;
                return true;
            }
            return false;
        }

        private bool ActualizaAnalisis()
        {
           clsAnalisisCapitalizacionRentas_CD objAnalisis_CD = new clsAnalisisCapitalizacionRentas_CD();
           return objAnalisis_CD.ModificaAnalisis(this);
        }

        private bool EliminaAnalisis()
        {
            clsAnalisisCapitalizacionRentas_CD objAnalisis_CD = new clsAnalisisCapitalizacionRentas_CD();
            return objAnalisis_CD.EliminaAnalisis(this);
        }

        public bool DatosValidos()
        {
            return true;
        }

        public static clsAnalisisCapitalizacionRentas_CRN RecuperaAnalisis(clsTerreno_CRN objTerreno)
        {
            clsAnalisisCapitalizacionRentas_CRN objAnalisis = new clsAnalisisCapitalizacionRentas_CRN(objTerreno);
            clsAnalisisCapitalizacionRentas_CD objAnalisis_CD = new clsAnalisisCapitalizacionRentas_CD();
            dsInmoviliario.ACapitalizacionRow filaAnalisis = objAnalisis_CD.ObtieneAnalisis(objTerreno.Inmueble.Avaluo.IdAvaluo);
            if (filaAnalisis != null)
            {
                objAnalisis.Administracion = filaAnalisis.Administracion;
                objAnalisis.AnioActual = filaAnalisis.AnioActual;
                objAnalisis.AnioAnterior = filaAnalisis.AnioAnterior;
                objAnalisis.AniosConservacion = filaAnalisis.AniosConservacion;
                objAnalisis.DeduccionOpcional = filaAnalisis.DeduccionOpcional;
                objAnalisis.DepreciacionFiscal = filaAnalisis.DepreciacionFiscal;
                objAnalisis.EsModificado = true;
                objAnalisis.Fecha = filaAnalisis.Fecha;
                objAnalisis.Fuente = filaAnalisis.Fuente;
                objAnalisis.InflacionEstimada = filaAnalisis.InflacionEstimada;
                objAnalisis.INPC = filaAnalisis.INPC;
                objAnalisis.LinkFuente = filaAnalisis.Link;
                objAnalisis.Observaciones = filaAnalisis.Observaciones;
                objAnalisis.PorcentajeConservacion = filaAnalisis.PorcentajeConservacion;
                objAnalisis.Predial = filaAnalisis.Predial;
                objAnalisis.Seguro = filaAnalisis.Seguro;
                objAnalisis.SupAccesoriaRentaM2 = filaAnalisis.SupAccRentaM2;
                objAnalisis.TIIE = filaAnalisis.TIIE;
                objAnalisis.TipoDePersona = filaAnalisis.TipoPersona;
                objAnalisis.Vacios = filaAnalisis.Vacios;
            }
            return objAnalisis;
        }

        #endregion
    }
}
